.

The R Language: Part 02

R Objetcs

Variable Assignment

A basic concept in (statistical) programming is called a variable.

A variable allows you to store a value (e.g. 4) or an object (e.g. a function description) in R. You can then later use this variable’s name to easily access the value or the object that is stored within this variable.

Save information as an R objetc with the greater than sign followed by a minus, e.g. an arrow: <-

#name of new objetc         assignment operator, "gets"         information to store in the objetc
foo                                 <-                            42

Common R Workflow

Save output of one function as an R objetc to use in a second function

foo <- round(3.1415) + 1
foo
[1] 4
factorial(foo)
[1] 24

Remove objetcs from environment

You can remove an objetc with rm

fac_foo<-factorial(foo)
fac_foo
[1] 24
rm(foo)
rm(fac_foo)

To consider…

  • Object names cannot beggin with numbers. Wise to avoid names already in use.
mean<-mean(rnorm(100))
mean
[1] -0.06199669
?mean
rm(mean)
pi
[1] 3.141593
pi<-1
pi
[1] 1
rm(pi)
pi
[1] 3.141593
  • R will treat the lowercase and capital letters as different.

Data Structures

You can save more than a single number in an objetc by creating a vector, matrix, or array.

WorldPhones
     N.Amer Europe Asia S.Amer Oceania Africa Mid.Amer
1951  45939  21574 2876   1815    1646     89      555
1956  60423  29990 4708   2568    2366   1411      733
1957  64721  32510 5230   2695    2526   1546      773
1958  68484  35218 6662   2845    2691   1663      836
1959  71799  37598 6856   3000    2868   1769      911
1960  76036  40341 8220   3145    3054   1905     1008
1961  79831  43173 9053   3338    3224   2005     1076
class(WorldPhones)
[1] "matrix"

Vectors

  • Combine multiple elements into one dimensional array.

  • Create with the c function.

vec<-c(1,2,3,10,100)
vec
[1]   1   2   3  10 100

Matrices

  • Combine multiple elements into a two dimensional array.

  • Create with the matrix function.

            #vector of elements to go in the matrix     number of rows for matrix
mat<-matrix(data = c(1,2,3,4,5,6),                      nrow = 2)
mat
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
            #vector of elements to go in the matrix     number of rows for matrix
mat<-matrix(data = c(1,2,3,4,5,6),                      nrow = 3)
mat
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6
            #vector of elements to go in the matrix     number of cols for matrix
#rbind(c(1,2,3,4,5,6),c(1,2,3,4,5,6)*2)
mat<-matrix(c(1,2,3,4,5,6),ncol=2)
mat
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6

Math: element- wise

vec2<-vec
vec2<-vec + 4
vec; vec2
[1]   1   2   3  10 100
[1]   5   6   7  14 104
vec * 4 ; vec2 * 4
[1]   4   8  12  40 400
[1]  20  24  28  56 416
vec * vec ; vec2 * vec2; c(23,vec) * c(vec2,2);vec;vec2
[1]     1     4     9   100 10000
[1]    25    36    49   196 10816
[1]  115    6   14   42 1040  200
[1]   1   2   3  10 100
[1]   5   6   7  14 104

Matrix multiplication

inner

mat<-matrix(c(1,2,3,4,5,6,7,8,9),ncol=3)
vec; vec %*% vec; mat;mat %*% mat
[1]   1   2   3  10 100
      [,1]
[1,] 10114
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
     [,1] [,2] [,3]
[1,]   30   66  102
[2,]   36   81  126
[3,]   42   96  150

outer

mat<-matrix(c(1,2,3,4,5,6),ncol=2)
vec; vec %o% vec; mat; mat %o% mat; mat %o% vec
[1]   1   2   3  10 100
     [,1] [,2] [,3] [,4]  [,5]
[1,]    1    2    3   10   100
[2,]    2    4    6   20   200
[3,]    3    6    9   30   300
[4,]   10   20   30  100  1000
[5,]  100  200  300 1000 10000
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6
, , 1, 1

     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6

, , 2, 1

     [,1] [,2]
[1,]    2    8
[2,]    4   10
[3,]    6   12

, , 3, 1

     [,1] [,2]
[1,]    3   12
[2,]    6   15
[3,]    9   18

, , 1, 2

     [,1] [,2]
[1,]    4   16
[2,]    8   20
[3,]   12   24

, , 2, 2

     [,1] [,2]
[1,]    5   20
[2,]   10   25
[3,]   15   30

, , 3, 2

     [,1] [,2]
[1,]    6   24
[2,]   12   30
[3,]   18   36

, , 1

     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6

, , 2

     [,1] [,2]
[1,]    2    8
[2,]    4   10
[3,]    6   12

, , 3

     [,1] [,2]
[1,]    3   12
[2,]    6   15
[3,]    9   18

, , 4

     [,1] [,2]
[1,]   10   40
[2,]   20   50
[3,]   30   60

, , 5

     [,1] [,2]
[1,]  100  400
[2,]  200  500
[3,]  300  600

transpose

mat
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6
t(mat)
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6

Data types

R can recognize different types of data.

We’ll look at four basic types:

  • numbers
  • character strings (text)
  • logical
  • factor

numeric

  • Any number, no quotes.
  • Appropiate for math.
12+4
[1] 16
3000000
[1] 3e+06
class(0.000001)
[1] "numeric"

character

  • Any symbols surronded by quotes.
  • Appropiate for words, variable names, messages, any text.
print("hello")
[1] "hello"
print('hello')
[1] "hello"
# print("hello') ESTO ESTÁ MAL
class("hello")
[1] "character"
"12+4"
[1] "12+4"
class("12+4")
[1] "character"
#"hello" + "world"
nchar("hello")
[1] 5
paste("hello","world",sep=",");paste("hello","world",sep=" 2342eafdsghsIJGBJmdxfghvb ")
[1] "hello,world"
[1] "hello 2342eafdsghsIJGBJmdxfghvb world"
paste("hello","world",sep=",");paste("como","estas",sep="_");
[1] "hello,world"
[1] "como_estas"
paste(paste("hello","world",sep=","),paste("como","estas",sep="_"),2,sep="::"); paste(paste("hello","world",sep=","),paste("como","estas",sep="_"),"2",sep="::"); paste("hola","sin","espacios",sep="");paste0("hola","sin","espacios")
[1] "hello,world::como_estas::2"
[1] "hello,world::como_estas::2"
[1] "holasinespacios"
[1] "holasinespacios"

To consider…

wich are numbers?

1; "1"; "one"
[1] 1
[1] "1"
[1] "one"
c(1, "1","one")
[1] "1"   "1"   "one"

logical

TRUE or FALSE - R’s form of binary data. - Useful for logical tests. - And Very Useful when whe want to filter datasets…

3<4
[1] TRUE
x <- c(1, 2, 3, 4, 5)
x
[1] 1 2 3 4 5
x > 3
[1] FALSE FALSE FALSE  TRUE  TRUE
x >= 3
[1] FALSE FALSE  TRUE  TRUE  TRUE
x < 3
[1]  TRUE  TRUE FALSE FALSE FALSE
x <= 3
[1]  TRUE  TRUE  TRUE FALSE FALSE
x == 3
[1] FALSE FALSE  TRUE FALSE FALSE
x != 3
[1]  TRUE  TRUE FALSE  TRUE  TRUE
x = 3
c(3,4,5,6) %in% c(2, 3, 4) 
[1]  TRUE  TRUE FALSE FALSE
titanic2<-read.csv("data/titanic2.csv",header = T)
titanic2
library(dplyr)
titanic2%>%
  filter(age=="adult")
titanic2%>%
  filter(class=="1st")
titanic2%>%
  filter(male<mean(male))
titanic2%>%
  filter(female>=mean(female))
unique(titanic2$class)
[1] 1st  2nd  3rd  Crew
Levels: 1st 2nd 3rd Crew
unique(titanic2$age)
[1] adult child
Levels: adult child
titanic2%>%
  filter(fate!="survived" & 
           as.numeric(class)>=3 & 
           as.numeric(age)<2)
titanic2%>%
  filter(fate=="survived" & 
           as.numeric(class)>=3 & 
           as.numeric(age)<2)
titanic2%>%
  filter(fate=="survived" & 
           class%in%c("1st","3rd"))
titanic2%>%
  filter(fate!="survived" & 
           class%in%c("1st","3rd"))
class(TRUE)
[1] "logical"
class(T) ; class(F)
[1] "logical"
[1] "logical"
class(3<4)
[1] "logical"

factor

R’s form of categorical data. Saved as an integer with a set of labels (e.g. levels)

fac<-factor(c("a","b","c"))
fac
[1] a b c
Levels: a b c
class(fac)
[1] "factor"

One proof that factor makes sense

titanic2
library(ggplot2)
gg<-ggplot(titanic2,aes(x=class,y=age))
gg + geom_point(aes(size=male))

gg + geom_point(aes(color=fate))

gg01<-gg + geom_point(aes(color=fate,size=male+female))
gg01

library(plotly)
ggplotly(gg01)

To consider…

  • Remember that if you want to assign a number or an object to a variable in R, you can make use of the assignment operator <-. Alternatively, you can use =, but <- is widely preferred in the R community.
# Assign a value to the variables my_apples and my_oranges
my_apples  <- 5
my_oranges <- 6
# Add these two variables together
my_apples + my_oranges
[1] 11
# Create the variable my_fruit
my_fruit <- my_apples + my_oranges

watch out!

Be careful with the operations between different types/classes of objects

# Assign a value to the variable my_apples
my_apples <- 5 
# Fix the assignment of my_oranges
my_oranges <- "six" 
# Create the variable my_fruit and print it out
# my_fruit <- my_apples + my_oranges
class(my_oranges)
[1] "character"
class(my_oranges)
[1] "character"

So, in general, it’s a good idea to check that the objetcs that are opperating between each other, are of the same class/type or we have to be conscients that sometimes, if the types are not equals but they are “almost operables”, R will change at least one of them to a type that make both be “totaly operables”.

There could be some warnings about this… it could be a good idea to knoe a little more about the data types that will be jumping in at our work.

Saving differents types in one single object…

On a Vector…

vec<-c(1,"R","TRUE")
class(vec)
[1] "character"
vec
[1] "1"    "R"    "TRUE"

Sure a Matrix will do it…

matriz_de_Camilo<-matrix(cbind(c(1,2,3),
                         c("R","S","T"),
                         c(TRUE,FALSE,TRUE)),ncol=3)
class(matriz_de_Camilo)
[1] "matrix"
matriz_de_Camilo
     [,1] [,2] [,3]   
[1,] "1"  "R"  "TRUE" 
[2,] "2"  "S"  "FALSE"
[3,] "3"  "T"  "TRUE" 
for(row_tmp in 1:nrow(matriz_de_Camilo)){
  print(class(matriz_de_Camilo[row_tmp,]))
}
[1] "character"
[1] "character"
[1] "character"
  
for(col_tmp in 1:ncol(matriz_de_Camilo)){
  print(class(matriz_de_Camilo[,col_tmp]))
}
[1] "character"
[1] "character"
[1] "character"
  
matriz_de_Camilo
     [,1] [,2] [,3]   
[1,] "1"  "R"  "TRUE" 
[2,] "2"  "S"  "FALSE"
[3,] "3"  "T"  "TRUE" 

What the … is R doing?!

Always remember Coercion

Always remember Coercion

So, isn’t there any way we I can do it?

Really? ;(

There is a way… Thank God for the data frames

And for the lists

Data frames

df<-data.frame(c(1,2,3),
               c("R","S","T"),
               c(TRUE,FALSE,TRUE))
df
df_de_Camilo<-as.data.frame(matriz_de_Camilo)
df_de_Camilo
as.data.frame(matriz_de_Camilo,stringsAsFactors = F)

When we read a .csv file and store it on a object, that will be a data.frame class

titanic2 ## remember how we got this object: read.csv("data/titanic2.csv",header = T)
class(titanic2)
[1] "data.frame"

And now, just because it’s worthy…

  • There are some types of objects very similar to the data frames but that are not exactly one of those

  • They came from the package dplyr (one of my favorites) and its class is called tibble (nickname: data_frame) instead of data.frame

  • Example:

library(nycflights13)
flights
class(flights)
[1] "tbl_df"     "tbl"        "data.frame"
  • Print on console:

  • titanic2 &, afterwards
  • flights

  • Do you see any difference?

List

nlst<-list(one=1,two=2,many=c(1,2,3))
nlst
$one
[1] 1

$two
[1] 2

$many
[1] 1 2 3
nlst<-list("Eduardo"=df_de_Camilo,"Camilo"=matriz_de_Camilo,"Carlos"=c(T,FALSE,TRUE,F))
#Print directly on console
nlst
$Eduardo

$Camilo
     [,1] [,2] [,3]   
[1,] "1"  "R"  "TRUE" 
[2,] "2"  "S"  "FALSE"
[3,] "3"  "T"  "TRUE" 

$Carlos
[1]  TRUE FALSE  TRUE FALSE
nlst$Eduardo
#Print directly on console
nlst[1]
$Eduardo
NA
#Print directly on console
nlst[[1]]
nlst02<-list("Eduardo"=df_de_Camilo,"Camilo"=matriz_de_Camilo,"Carlos"=c(T,FALSE,TRUE,F),"unalistadentrodeunalista"=nlst)
#Print directly on console
nlst02
$Eduardo

$Camilo
     [,1] [,2] [,3]   
[1,] "1"  "R"  "TRUE" 
[2,] "2"  "S"  "FALSE"
[3,] "3"  "T"  "TRUE" 

$Carlos
[1]  TRUE FALSE  TRUE FALSE

$unalistadentrodeunalista
$unalistadentrodeunalista$Eduardo

$unalistadentrodeunalista$Camilo
     [,1] [,2] [,3]   
[1,] "1"  "R"  "TRUE" 
[2,] "2"  "S"  "FALSE"
[3,] "3"  "T"  "TRUE" 

$unalistadentrodeunalista$Carlos
[1]  TRUE FALSE  TRUE FALSE
LS0tCnRpdGxlOiAiIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIGRmX3ByaW50OiBwYWdlZAogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKLS0tCgojIDxhPjxpbWcgc3JjPSd3d3cvYmJ2YV91YWR5MDIucG5nJyBhbGlnbj0icmlnaHQiIGhlaWdodD0iMTM5IiAvPjwvYT4KICAgLiA8YnIvPgoKI1RoZSBSIExhbmd1YWdlOiBQYXJ0IDAyCgojIyBSIE9iamV0Y3MKCiMjIyBWYXJpYWJsZSBBc3NpZ25tZW50CkEgYmFzaWMgY29uY2VwdCBpbiAoc3RhdGlzdGljYWwpIHByb2dyYW1taW5nIGlzIGNhbGxlZCBhICoqdmFyaWFibGUqKi4gCgpBIHZhcmlhYmxlIGFsbG93cyB5b3UgdG8gc3RvcmUgYSB2YWx1ZSAoZS5nLiA0KSBvciBhbiBvYmplY3QgKGUuZy4gYSBmdW5jdGlvbiBkZXNjcmlwdGlvbikgaW4gUi4gWW91IGNhbiB0aGVuIGxhdGVyIHVzZSB0aGlzIHZhcmlhYmxlJ3MgbmFtZSB0byBlYXNpbHkgYWNjZXNzIHRoZSB2YWx1ZSBvciB0aGUgb2JqZWN0IHRoYXQgaXMgc3RvcmVkIHdpdGhpbiB0aGlzIHZhcmlhYmxlLiAKClNhdmUgaW5mb3JtYXRpb24gYXMgYW4gUiBvYmpldGMgd2l0aCB0aGUgKmdyZWF0ZXIgdGhhbiogc2lnbiBmb2xsb3dlZCBieSAqYSBtaW51cyosIGUuZy4gYW4gYXJyb3c6IGA8LWAKYGBge3J9CiNuYW1lIG9mIG5ldyBvYmpldGMgICAgICAgICBhc3NpZ25tZW50IG9wZXJhdG9yLCAiZ2V0cyIgICAgICAgICBpbmZvcm1hdGlvbiB0byBzdG9yZSBpbiB0aGUgb2JqZXRjCmZvbyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwtICAgICAgICAgICAgICAgICAgICAgICAgICAgIDQyCmBgYAoKIyMjIENvbW1vbiBSIFdvcmtmbG93ClNhdmUgb3V0cHV0IG9mIG9uZSBmdW5jdGlvbiBhcyBhbiBSIG9iamV0YyB0byB1c2UgaW4gYSBzZWNvbmQgZnVuY3Rpb24KYGBge3J9CmZvbyA8LSByb3VuZCgzLjE0MTUpICsgMQpmb28KYGBgCgpgYGB7cn0KZmFjdG9yaWFsKGZvbykKYGBgCgojIyBSZW1vdmUgb2JqZXRjcyBmcm9tIGVudmlyb25tZW50CllvdSBjYW4gcmVtb3ZlIGFuIG9iamV0YyB3aXRoIGBybWAKYGBge3J9CmZhY19mb288LWZhY3RvcmlhbChmb28pCmZhY19mb28KYGBgCgpgYGB7cn0Kcm0oZm9vKQpybShmYWNfZm9vKQpgYGAKCiMjIyBUbyBjb25zaWRlci4uLgoKLSBPYmplY3QgbmFtZXMgY2Fubm90IGJlZ2dpbiB3aXRoIG51bWJlcnMuIFdpc2UgdG8gYXZvaWQgbmFtZXMgYWxyZWFkeSBpbiB1c2UuCgpgYGB7cn0KbWVhbjwtbWVhbihybm9ybSgxMDApKQptZWFuCj9tZWFuCmBgYApgYGB7cn0Kcm0obWVhbikKcGkKcGk8LTEKcGkKcm0ocGkpCnBpCmBgYAoKLSBSIHdpbGwgdHJlYXQgdGhlIGxvd2VyY2FzZSBhbmQgY2FwaXRhbCBsZXR0ZXJzIGFzIGRpZmZlcmVudC4KCgojIyBEYXRhIFN0cnVjdHVyZXMKCllvdSBjYW4gc2F2ZSBtb3JlIHRoYW4gYSBzaW5nbGUgbnVtYmVyIGluIGFuIG9iamV0YyBieSBjcmVhdGluZyBhICp2ZWN0b3IqLCAqbWF0cml4Kiwgb3IgKmFycmF5Ki4KCmBgYHtyfQpXb3JsZFBob25lcwpjbGFzcyhXb3JsZFBob25lcykKYGBgCgoKIyMjIFZlY3RvcnMKCi0gQ29tYmluZSBtdWx0aXBsZSBlbGVtZW50cyBpbnRvIG9uZSBkaW1lbnNpb25hbCBhcnJheS4KCi0gQ3JlYXRlIHdpdGggdGhlIGBjYCBmdW5jdGlvbi4KYGBge3J9CnZlYzwtYygxLDIsMywxMCwxMDApCnZlYwpgYGAKCiMjIyBNYXRyaWNlcwoKLSBDb21iaW5lIG11bHRpcGxlIGVsZW1lbnRzIGludG8gYSB0d28gZGltZW5zaW9uYWwgYXJyYXkuCgotIENyZWF0ZSB3aXRoIHRoZSBgbWF0cml4YCBmdW5jdGlvbi4KYGBge3J9CiAgICAgICAgICAgICN2ZWN0b3Igb2YgZWxlbWVudHMgdG8gZ28gaW4gdGhlIG1hdHJpeCAgICAgbnVtYmVyIG9mIHJvd3MgZm9yIG1hdHJpeAoKbWF0PC1tYXRyaXgoZGF0YSA9IGMoMSwyLDMsNCw1LDYpLCAgICAgICAgICAgICAgICAgICAgICBucm93ID0gMikKbWF0CmBgYAoKYGBge3J9CiAgICAgICAgICAgICN2ZWN0b3Igb2YgZWxlbWVudHMgdG8gZ28gaW4gdGhlIG1hdHJpeCAgICAgbnVtYmVyIG9mIHJvd3MgZm9yIG1hdHJpeAoKbWF0PC1tYXRyaXgoZGF0YSA9IGMoMSwyLDMsNCw1LDYpLCAgICAgICAgICAgICAgICAgICAgICBucm93ID0gMykKbWF0CmBgYAoKCmBgYHtyfQogICAgICAgICAgICAjdmVjdG9yIG9mIGVsZW1lbnRzIHRvIGdvIGluIHRoZSBtYXRyaXggICAgIG51bWJlciBvZiBjb2xzIGZvciBtYXRyaXgKI3JiaW5kKGMoMSwyLDMsNCw1LDYpLGMoMSwyLDMsNCw1LDYpKjIpCm1hdDwtbWF0cml4KGMoMSwyLDMsNCw1LDYpLG5jb2w9MikKbWF0CmBgYAoKIyMjIE1hdGg6IGVsZW1lbnQtIHdpc2UKYGBge3J9CnZlYzI8LXZlYwp2ZWMyPC12ZWMgKyA0CnZlYzsgdmVjMgpgYGAKCmBgYHtyfQp2ZWMgKiA0IDsgdmVjMiAqIDQKYGBgCgpgYGB7cn0KdmVjICogdmVjIDsgdmVjMiAqIHZlYzI7IGMoMjMsdmVjKSAqIGModmVjMiwyKTt2ZWM7dmVjMgpgYGAKCiMjIyBNYXRyaXggbXVsdGlwbGljYXRpb24KCioqaW5uZXIqKgpgYGB7cn0KbWF0PC1tYXRyaXgoYygxLDIsMyw0LDUsNiw3LDgsOSksbmNvbD0zKQp2ZWM7IHZlYyAlKiUgdmVjOyBtYXQ7bWF0ICUqJSBtYXQKYGBgCgoqKm91dGVyKioKYGBge3J9CgptYXQ8LW1hdHJpeChjKDEsMiwzLDQsNSw2KSxuY29sPTIpCnZlYzsgdmVjICVvJSB2ZWM7IG1hdDsgbWF0ICVvJSBtYXQ7IG1hdCAlbyUgdmVjCmBgYAoKKip0cmFuc3Bvc2UqKgpgYGB7cn0KbWF0CmBgYAoKYGBge3J9CnQobWF0KQpgYGAKCiMjRGF0YSB0eXBlcwpSIGNhbiByZWNvZ25pemUgZGlmZmVyZW50IHR5cGVzIG9mIGRhdGEuCgpXZSdsbCBsb29rIGF0IGZvdXIgYmFzaWMgdHlwZXM6CgotIG51bWJlcnMKLSBjaGFyYWN0ZXIgc3RyaW5ncyAodGV4dCkKLSBsb2dpY2FsCi0gZmFjdG9yCgoKIyMjIG51bWVyaWMKLSBBbnkgbnVtYmVyLCBubyBxdW90ZXMuIAotIEFwcHJvcGlhdGUgZm9yIG1hdGguCgpgYGB7cn0KMTIrNApgYGAKCmBgYHtyfQozMDAwMDAwCmBgYAoKYGBge3J9CmNsYXNzKDAuMDAwMDAxKQpgYGAKCiMjIyBjaGFyYWN0ZXIKCi0gQW55IHN5bWJvbHMgc3Vycm9uZGVkIGJ5IHF1b3Rlcy4KLSBBcHByb3BpYXRlIGZvciB3b3JkcywgdmFyaWFibGUgbmFtZXMsIG1lc3NhZ2VzLCBhbnkgdGV4dC4KCmBgYHtyfQpwcmludCgiaGVsbG8iKQpwcmludCgnaGVsbG8nKQoKIyBwcmludCgiaGVsbG8nKSBFU1RPIEVTVMOBIE1BTApgYGAKCmBgYHtyfQpjbGFzcygiaGVsbG8iKQpgYGAKCgpgYGB7cn0KIjEyKzQiCmBgYAoKYGBge3J9CmNsYXNzKCIxMis0IikKYGBgCgpgYGB7cn0KIyJoZWxsbyIgKyAid29ybGQiCmBgYAoKYGBge3J9Cm5jaGFyKCJoZWxsbyIpCmBgYAoKYGBge3J9CnBhc3RlKCJoZWxsbyIsIndvcmxkIixzZXA9IiwiKTtwYXN0ZSgiaGVsbG8iLCJ3b3JsZCIsc2VwPSIgMjM0MmVhZmRzZ2hzSUpHQkptZHhmZ2h2YiAiKQpgYGAKCgpgYGB7cn0KcGFzdGUoImhlbGxvIiwid29ybGQiLHNlcD0iLCIpO3Bhc3RlKCJjb21vIiwiZXN0YXMiLHNlcD0iXyIpOwoKcGFzdGUocGFzdGUoImhlbGxvIiwid29ybGQiLHNlcD0iLCIpLHBhc3RlKCJjb21vIiwiZXN0YXMiLHNlcD0iXyIpLDIsc2VwPSI6OiIpOyBwYXN0ZShwYXN0ZSgiaGVsbG8iLCJ3b3JsZCIsc2VwPSIsIikscGFzdGUoImNvbW8iLCJlc3RhcyIsc2VwPSJfIiksIjIiLHNlcD0iOjoiKTsgcGFzdGUoImhvbGEiLCJzaW4iLCJlc3BhY2lvcyIsc2VwPSIiKTtwYXN0ZTAoImhvbGEiLCJzaW4iLCJlc3BhY2lvcyIpCmBgYAoKIyMjIFRvIGNvbnNpZGVyLi4uCioqd2ljaCBhcmUgbnVtYmVycz8qKgoKYGBge3J9CjE7ICIxIjsgIm9uZSIKYGBgCmBgYHtyfQpjKDEsICIxIiwib25lIikKYGBgCiMjIyBsb2dpY2FsCmBUUlVFYCBvciBgRkFMU0VgCi0gUidzIGZvcm0gb2YgYmluYXJ5IGRhdGEuIAotIFVzZWZ1bCBmb3IgbG9naWNhbCB0ZXN0cy4KLSBBbmQgVmVyeSBVc2VmdWwgd2hlbiB3aGUgd2FudCB0byBmaWx0ZXIgZGF0YXNldHMuLi4KCmBgYHtyfQozPDQKeCA8LSBjKDEsIDIsIDMsIDQsIDUpCngKeCA+IDMKeCA+PSAzCnggPCAzCnggPD0gMwp4ID09IDMKeCAhPSAzCnggPSAzCgpjKDMsNCw1LDYpICVpbiUgYygyLCAzLCA0KSAKCmBgYAoKYGBge3J9CnRpdGFuaWMyPC1yZWFkLmNzdigiZGF0YS90aXRhbmljMi5jc3YiLGhlYWRlciA9IFQpCnRpdGFuaWMyCmBgYAoKYGBge3J9CmxpYnJhcnkoZHBseXIpCnRpdGFuaWMyJT4lCiAgZmlsdGVyKGFnZT09ImFkdWx0IikKYGBgCgpgYGB7cn0KdGl0YW5pYzIlPiUKICBmaWx0ZXIoY2xhc3M9PSIxc3QiKQpgYGAKCmBgYHtyfQp0aXRhbmljMiU+JQogIGZpbHRlcihtYWxlPG1lYW4obWFsZSkpCmBgYAoKYGBge3J9CnRpdGFuaWMyJT4lCiAgZmlsdGVyKGZlbWFsZT49bWVhbihmZW1hbGUpKQpgYGAKYGBge3J9CnVuaXF1ZSh0aXRhbmljMiRjbGFzcykKdW5pcXVlKHRpdGFuaWMyJGFnZSkKYGBgCmBgYHtyfQp0aXRhbmljMiU+JQogIGZpbHRlcihmYXRlIT0ic3Vydml2ZWQiICYgCiAgICAgICAgICAgYXMubnVtZXJpYyhjbGFzcyk+PTMgJiAKICAgICAgICAgICBhcy5udW1lcmljKGFnZSk8MikKYGBgCgpgYGB7cn0KdGl0YW5pYzIlPiUKICBmaWx0ZXIoZmF0ZT09InN1cnZpdmVkIiAmIAogICAgICAgICAgIGFzLm51bWVyaWMoY2xhc3MpPj0zICYgCiAgICAgICAgICAgYXMubnVtZXJpYyhhZ2UpPDIpCmBgYAoKYGBge3J9CnRpdGFuaWMyJT4lCiAgZmlsdGVyKGZhdGU9PSJzdXJ2aXZlZCIgJiAKICAgICAgICAgICBjbGFzcyVpbiVjKCIxc3QiLCIzcmQiKSkKYGBgCgpgYGB7cn0KdGl0YW5pYzIlPiUKICBmaWx0ZXIoZmF0ZSE9InN1cnZpdmVkIiAmIAogICAgICAgICAgIGNsYXNzJWluJWMoIjFzdCIsIjNyZCIpKQpgYGAKCgoKYGBge3J9CmNsYXNzKFRSVUUpCmBgYAoKYGBge3J9CmNsYXNzKFQpIDsgY2xhc3MoRikKYGBgCgpgYGB7cn0KY2xhc3MoMzw0KQpgYGAKCiMjIGZhY3RvcgpSJ3MgZm9ybSBvZiBjYXRlZ29yaWNhbCBkYXRhLiBTYXZlZCBhcyBhbiBpbnRlZ2VyIHdpdGggYSBzZXQgb2YgbGFiZWxzIChlLmcuIGxldmVscykKYGBge3J9CmZhYzwtZmFjdG9yKGMoImEiLCJiIiwiYyIpKQpmYWMKYGBgCmBgYHtyfQpjbGFzcyhmYWMpCmBgYAoqKk9uZSBwcm9vZiB0aGF0ICpmYWN0b3IqIG1ha2VzIHNlbnNlKioKYGBge3J9CnRpdGFuaWMyCmBgYAoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKZ2c8LWdncGxvdCh0aXRhbmljMixhZXMoeD1jbGFzcyx5PWFnZSkpCmdnICsgZ2VvbV9wb2ludChhZXMoc2l6ZT1tYWxlKSkKYGBgCmBgYHtyfQpnZyArIGdlb21fcG9pbnQoYWVzKGNvbG9yPWZhdGUpKQpgYGAKCmBgYHtyfQpnZzAxPC1nZyArIGdlb21fcG9pbnQoYWVzKGNvbG9yPWZhdGUsc2l6ZT1tYWxlK2ZlbWFsZSkpCmdnMDEKYGBgCmBgYHtyLGZpZy5oZWlnaHQ9NixmaWcud2lkdGg9MTB9CmxpYnJhcnkocGxvdGx5KQpnZ3Bsb3RseShnZzAxKQpgYGAKCgoKIyMjIFRvIGNvbnNpZGVyLi4uCgotIFJlbWVtYmVyIHRoYXQgaWYgeW91IHdhbnQgdG8gYXNzaWduIGEgbnVtYmVyIG9yIGFuIG9iamVjdCB0byBhIHZhcmlhYmxlIGluIFIsIHlvdSBjYW4gbWFrZSB1c2Ugb2YgdGhlIGFzc2lnbm1lbnQgb3BlcmF0b3IgYDwtYC4gQWx0ZXJuYXRpdmVseSwgeW91IGNhbiB1c2UgYD1gLCBidXQgYDwtYCBpcyB3aWRlbHkgcHJlZmVycmVkIGluIHRoZSBSIGNvbW11bml0eS4KCmBgYHtyLCBlY2hvPVRSVUV9CiMgQXNzaWduIGEgdmFsdWUgdG8gdGhlIHZhcmlhYmxlcyBteV9hcHBsZXMgYW5kIG15X29yYW5nZXMKbXlfYXBwbGVzICA8LSA1Cm15X29yYW5nZXMgPC0gNgoKIyBBZGQgdGhlc2UgdHdvIHZhcmlhYmxlcyB0b2dldGhlcgpteV9hcHBsZXMgKyBteV9vcmFuZ2VzCgojIENyZWF0ZSB0aGUgdmFyaWFibGUgbXlfZnJ1aXQKbXlfZnJ1aXQgPC0gbXlfYXBwbGVzICsgbXlfb3JhbmdlcwpgYGAKCiMjIHdhdGNoIG91dCEKQmUgY2FyZWZ1bCB3aXRoIHRoZSBvcGVyYXRpb25zIGJldHdlZW4gZGlmZmVyZW50IHR5cGVzL2NsYXNzZXMgb2Ygb2JqZWN0cwpgYGB7ciwgZWNobz1UUlVFfQojIEFzc2lnbiBhIHZhbHVlIHRvIHRoZSB2YXJpYWJsZSBteV9hcHBsZXMKbXlfYXBwbGVzIDwtIDUgCgojIEZpeCB0aGUgYXNzaWdubWVudCBvZiBteV9vcmFuZ2VzCm15X29yYW5nZXMgPC0gInNpeCIgCmBgYAoKYGBge3IsIGVjaG89VFJVRX0KIyBDcmVhdGUgdGhlIHZhcmlhYmxlIG15X2ZydWl0IGFuZCBwcmludCBpdCBvdXQKIyBteV9mcnVpdCA8LSBteV9hcHBsZXMgKyBteV9vcmFuZ2VzCmBgYAoKYGBge3IsIGVjaG89VFJVRX0KY2xhc3MobXlfb3JhbmdlcykKYGBgCmBgYHtyLCBlY2hvPVRSVUV9CmNsYXNzKG15X29yYW5nZXMpCmBgYApTbywgaW4gZ2VuZXJhbCwgaXQncyBhIGdvb2QgaWRlYSB0byBjaGVjayB0aGF0IHRoZSBvYmpldGNzIHRoYXQgYXJlIG9wcGVyYXRpbmcgYmV0d2VlbiBlYWNoIG90aGVyLCBhcmUgb2YgdGhlIHNhbWUgY2xhc3MvdHlwZSBvciB3ZSBoYXZlIHRvIGJlIGNvbnNjaWVudHMgdGhhdCBzb21ldGltZXMsIGlmIHRoZSB0eXBlcyBhcmUgbm90IGVxdWFscyBidXQgdGhleSBhcmUgImFsbW9zdCBvcGVyYWJsZXMiLCAqUiogd2lsbCBjaGFuZ2UgYXQgbGVhc3Qgb25lIG9mIHRoZW0gdG8gYSB0eXBlIHRoYXQgbWFrZSBib3RoIGJlICJ0b3RhbHkgb3BlcmFibGVzIi4gCgpUaGVyZSBjb3VsZCBiZSBzb21lIHdhcm5pbmdzIGFib3V0IHRoaXMuLi4gaXQgY291bGQgYmUgYSBnb29kIGlkZWEgdG8ga25vZSBhIGxpdHRsZSBtb3JlIGFib3V0IHRoZSAqKmRhdGEgdHlwZXMqKiB0aGF0IHdpbGwgYmUganVtcGluZyBpbiBhdCBvdXIgd29yay4KCiMjIFNhdmluZyBkaWZmZXJlbnRzIHR5cGVzIGluIG9uZSBzaW5nbGUgb2JqZWN0Li4uCgoqT24gYSBWZWN0b3IuLi4qCmBgYHtyfQp2ZWM8LWMoMSwiUiIsIlRSVUUiKQpgYGAKCmBgYHtyfQpjbGFzcyh2ZWMpCmBgYAoKYGBge3J9CnZlYwpgYGAKCipTdXJlIGEgTWF0cml4IHdpbGwgZG8gaXQuLi4qCmBgYHtyfQptYXRyaXpfZGVfQ2FtaWxvPC1tYXRyaXgoY2JpbmQoYygxLDIsMyksCiAgICAgICAgICAgICAgICAgICAgICAgICBjKCJSIiwiUyIsIlQiKSwKICAgICAgICAgICAgICAgICAgICAgICAgIGMoVFJVRSxGQUxTRSxUUlVFKSksbmNvbD0zKQpgYGAKCmBgYHtyfQpjbGFzcyhtYXRyaXpfZGVfQ2FtaWxvKQpgYGAKCmBgYHtyfQptYXRyaXpfZGVfQ2FtaWxvCmBgYAoKYGBge3J9CmZvcihyb3dfdG1wIGluIDE6bnJvdyhtYXRyaXpfZGVfQ2FtaWxvKSl7CiAgcHJpbnQoY2xhc3MobWF0cml6X2RlX0NhbWlsb1tyb3dfdG1wLF0pKQp9CiAgCmBgYAoKYGBge3J9CmZvcihjb2xfdG1wIGluIDE6bmNvbChtYXRyaXpfZGVfQ2FtaWxvKSl7CiAgcHJpbnQoY2xhc3MobWF0cml6X2RlX0NhbWlsb1ssY29sX3RtcF0pKQp9CiAgCmBgYAoKYGBge3J9Cm1hdHJpel9kZV9DYW1pbG8KYGBgCgoqV2hhdCB0aGUgLi4uIGlzIFIgZG9pbmc/ISoKCiFbQWx3YXlzIHJlbWVtYmVyIENvZXJjaW9uXSh3d3cvY29lcmNpb24ucG5nKQoKKipTbywgaXNuJ3QgdGhlcmUgYW55IHdheSB3ZSBJIGNhbiAgZG8gaXQ/KioKCiFbIF0od3d3L2h1bGtfcGVuc2F0aXZlLmpwZykKCgoqKlJlYWxseT8gOyggKioKCiFbIF0od3d3L2lyb21hbl9wZW5zYXRpdmUuanBnKQoKCioqVGhlcmUgaXMgYSB3YXkuLi4gVGhhbmsgR29kIGZvciB0aGUgYGRhdGEgZnJhbWVzYC4uLioqCgoKCiFbIF0od3d3L1Rob3JfeWVpaWkuanBnKQoKCioqQW5kIGZvciB0aGUgYGxpc3RzYC4uLioqCgohWyBdKHd3dy95ZWVlYWFhaGhoLWxva2kuZ2lmKQoKCiMjIERhdGEgZnJhbWVzCmBgYHtyfQpkZjwtZGF0YS5mcmFtZShjKDEsMiwzKSwKICAgICAgICAgICAgICAgYygiUiIsIlMiLCJUIiksCiAgICAgICAgICAgICAgIGMoVFJVRSxGQUxTRSxUUlVFKSkKZGYKYGBgCgpgYGB7cn0KZGZfZGVfQ2FtaWxvPC1hcy5kYXRhLmZyYW1lKG1hdHJpel9kZV9DYW1pbG8pCmRmX2RlX0NhbWlsbwpgYGAKYGBge3J9CmFzLmRhdGEuZnJhbWUobWF0cml6X2RlX0NhbWlsbyxzdHJpbmdzQXNGYWN0b3JzID0gRikKYGBgCgoqKldoZW4gd2UgcmVhZCBhICouY3N2KiBmaWxlIGFuZCBzdG9yZSBpdCBvbiBhIG9iamVjdCwgdGhhdCB3aWxsIGJlIGEgYGRhdGEuZnJhbWVgIGNsYXNzKioKCmBgYHtyfQp0aXRhbmljMiAjIyByZW1lbWJlciBob3cgd2UgZ290IHRoaXMgb2JqZWN0OiByZWFkLmNzdigiZGF0YS90aXRhbmljMi5jc3YiLGhlYWRlciA9IFQpCmNsYXNzKHRpdGFuaWMyKQpgYGAKCioqQW5kIG5vdywganVzdCBiZWNhdXNlIGl0J3Mgd29ydGh5Li4uKioKCiFbIF0od3d3L3BpZXRyYWRhdGEucG5nKQoKLSBUaGVyZSBhcmUgc29tZSB0eXBlcyBvZiBvYmplY3RzIHZlcnkgc2ltaWxhciB0byB0aGUgYGRhdGEgZnJhbWVzYCBidXQgdGhhdCBhcmUgbm90IGV4YWN0bHkgb25lIG9mIHRob3NlCgotIFRoZXkgY2FtZSBmcm9tIHRoZSBwYWNrYWdlIGBkcGx5cmAgKihvbmUgb2YgbXkgZmF2b3JpdGVzKSogYW5kIGl0cyBjbGFzcyBpcyBjYWxsZWQgYHRpYmJsZWAgKihuaWNrbmFtZTogKipgZGF0YV9mcmFtZWAqKikqIGluc3RlYWQgb2YgKipgZGF0YS5mcmFtZWAqKgoKLSBFeGFtcGxlOgpgYGB7cn0KbGlicmFyeShueWNmbGlnaHRzMTMpCmZsaWdodHMKYGBgCgpgYGB7cn0KY2xhc3MoZmxpZ2h0cykKYGBgCgotIFByaW50IG9uIGNvbnNvbGU6CgogIC0gYHRpdGFuaWMyYAogICYsIGFmdGVyd2FyZHMKICAtIGBmbGlnaHRzYAogIAotIERvIHlvdSBzZWUgYW55IGRpZmZlcmVuY2U/CgojIyBMaXN0CgohWyBdKHd3dy9UaGViYXJuZXliYWcwMS5qcGcpCgohWyBdKHd3dy9UaGViYXJuZXliYWcwMi5qcGcpCmBgYHtyfQpubHN0PC1saXN0KG9uZT0xLHR3bz0yLG1hbnk9YygxLDIsMykpCm5sc3QKYGBgCmBgYHtyfQpubHN0PC1saXN0KCJFZHVhcmRvIj1kZl9kZV9DYW1pbG8sIkNhbWlsbyI9bWF0cml6X2RlX0NhbWlsbywiQ2FybG9zIj1jKFQsRkFMU0UsVFJVRSxGKSkKI1ByaW50IGRpcmVjdGx5IG9uIGNvbnNvbGUKbmxzdApgYGAKYGBge3J9Cm5sc3QkRWR1YXJkbwpgYGAKCmBgYHtyfQojUHJpbnQgZGlyZWN0bHkgb24gY29uc29sZQpubHN0WzFdCmBgYAoKYGBge3J9CiNQcmludCBkaXJlY3RseSBvbiBjb25zb2xlCm5sc3RbWzFdXQpgYGAKCmBgYHtyfQpubHN0MDI8LWxpc3QoIkVkdWFyZG8iPWRmX2RlX0NhbWlsbywiQ2FtaWxvIj1tYXRyaXpfZGVfQ2FtaWxvLCJDYXJsb3MiPWMoVCxGQUxTRSxUUlVFLEYpLCJ1bmFsaXN0YWRlbnRyb2RldW5hbGlzdGEiPW5sc3QpCiNQcmludCBkaXJlY3RseSBvbiBjb25zb2xlCm5sc3QwMgpgYGAKCmBgYHtyfQoKYGBgCgo=